package server

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"os"
	"strings"
)

func api_get_family_article_info(tx *sql.Tx, articleId int64) *ReturnStruct {
	//查找文章信息
	var article_id int64     //文章id
	var title string         //文章标题
	var content_delta string //文章delta内容
	var edit_person int64    //编辑人
	var edit_person_name string
	var edit_time string //编辑时间
	var create_person int64
	var create_person_name string
	err := tx.QueryRow("select a.id, title, IFNULL(content_delta, '{}') as content_delta, IFNULL(b.id, 0) as edit_person, IFNULL(b.name, '') as edit_person_name, edit_timestamp as edit_time, IFNULL(c.id, 0) as create_person, IFNULL(c.name, '') as create_person_name from tb_family_article a left join tb_person b on a.edit_person = b.id left join tb_person c on a.create_person = c.id where a.id = ?", articleId).Scan(&article_id, &title, &content_delta, &edit_person, &edit_person_name, &edit_time, &create_person, &create_person_name)
	if err != nil {
		return DBErrReturn("查找文章", err)
	}
	if article_id == 0 {
		return SvrErrReturn("查找文章失败")
	}

	//替换delta内容中的image
	rows, err := tx.Query("select id, filename from tb_family_article_pic where article = ?", article_id)
	if err != nil {
		return DBErrReturn("查找文章图片", err)
	}
	images, _ := SelectResultFromRows(rows)
	article_image_map := make(map[int64]string)
	for i := 0; i < len(images); i++ {
		val, _ := images[i]["id"]
		image_id, _ := val.(int64)
		val, _ = images[i]["filename"]
		filename, _ := val.(string)
		article_image_map[image_id] = filename
	}
	content_delta, err = DeltaUnInterpretImage(content_delta, article_image_map)
	if err != nil {
		return SvrErrReturn("替换图片失败-" + err.Error())
	}

	//查询评论
	comments, err := api_get_family_article_comments(tx, article_id)
	if err != nil {
		return DBErrReturn("查找文章评论", err)
	}

	//返回数据
	result := make(map[string]interface{})
	result["article_id"] = article_id
	result["title"] = title
	result["content_delta"] = content_delta
	result["edit_person"] = edit_person
	result["edit_person_name"] = edit_person_name
	result["edit_time"] = edit_time
	result["create_person"] = create_person
	result["create_person_name"] = create_person_name
	result["comments"] = comments
	return SuccRet(result)
}

func get_family_article_info(tx *sql.Tx, person_id int64, jsonData string) *ReturnStruct {
	type Param struct {
		Article int64 `json:"article"` //文章id
		Family  int64 `json:"family"`  //文章所属家族
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//校验article
	var count int64
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and family = ?", param.Article, param.Family).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return ParamErrReturn("校验数据异常")
	}

	return api_get_family_article_info(tx, param.Article)
}

//编辑文章信息
func edit_family_article_info(tx *sql.Tx, person_id int64, jsonData string) (returnVal *ReturnStruct) {
	type Param struct {
		Article     int64            `json:"article"`      //文章id，如果是新增，则取0
		Family      int64            `json:"family"`       //文章所属家族
		LocalImages map[int64]string `json:"local_images"` //本次上传的图片, ops中的下标 -> 图片名
		Delta       string           `json:"delta"`        //delta数据
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//校验article
	var count int64
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and family = ?", param.Article, param.Family).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return ParamErrReturn("校验数据异常")
	}

	//校验编辑人
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and create_person = ?", param.Article, person_id).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return SvrErrReturn("只有创建者可以编辑家族文章！")
	}

	//查询已有图片
	rows, err := tx.Query("select id, filename from tb_family_article_pic where article = ?", param.Article)
	if err != nil {
		return DBErrReturn("查询已有图片", err)
	}
	picsResult, _ := SelectResultFromRows(rows)
	picsExistCache := make(map[string]int64) //图片名字 -> 图片id
	for i := 0; i < len(picsResult); i++ {
		val := picsResult[i]["id"]
		image_id, _ := val.(int64)
		val = picsResult[i]["filename"]
		image_name, _ := val.(string)
		picsExistCache[image_name] = image_id
	}

	//保存本次上报的本地图片
	picsLocalCache := make(map[int64]int64) //ops下标 -> 图片id
	for ops_index, image_name := range param.LocalImages {
		result, err := tx.Exec("insert into tb_family_article_pic(article, filename) values (?, ?)", param.Article, image_name)
		if err != nil {
			return DBErrReturn("保存本地图片", err)
		}
		count, _ := result.RowsAffected()
		if count != 1 {
			return SvrErrReturn("保存本地图片失败")
		}
		image_id, _ := result.LastInsertId()
		picsLocalCache[ops_index] = image_id
	}

	//将delta中的image替换为id
	param.Delta, err = DeltaInterpretImage(param.Delta, picsExistCache, picsLocalCache)
	if err != nil {
		return SvrErrReturn("图片替换失败-" + err.Error())
	}

	//删除图片
	imageIds := make([]int64, 0)
	for _, image_id := range picsExistCache {
		imageIds = append(imageIds, image_id)
	}
	if len(imageIds) > 0 {
		sql := fmt.Sprintf("delete from tb_family_article_pic where article = ? and id in (%s)", strings.Join(ArrInt64ToArrStr(imageIds), ","))
		_, err = tx.Exec(sql, param.Article)
		if err != nil {
			return DBErrReturn("删除图片失败", err)
		}
	}
	//注意： 等接口调用完毕再删除图片，避免后续产生异常后回滚但图片已经删了
	defer func() {
		if returnVal.is_success() {
			for image_name := range picsExistCache {
				os.Remove("./file/" + image_name)
			}
		}
	}()

	//保存文章
	_, err = tx.Exec("update tb_family_article set content_delta = ? , edit_person = ?, edit_timestamp = CURRENT_TIMESTAMP() where id = ?", param.Delta, person_id, param.Article)
	if err != nil {
		return DBErrReturn("保存文章", err)
	}
	return api_get_family_article_info(tx, param.Article)
}

//新增文章, 只传标题
func add_family_article_by_title(tx *sql.Tx, person_id int64, jsonData string) *ReturnStruct {
	type Param struct {
		Family int64  `json:"family"` //家族id
		Title  string `json:"title"`  //文章标题
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//家族文章不能超过10000个
	var count int64
	err = tx.QueryRow("select count(*) from tb_family_article where family = ?", param.Family).Scan(&count)
	if err != nil {
		return DBErrReturn("查询文章个数", err)
	}
	if count > 10000 {
		return SvrErrReturn("个人文章已超过10000个，无法新增")
	}

	//新增文章
	result, err := tx.Exec("insert into tb_family_article(family, title, content_delta, edit_person, create_person) values (?, ?, ?, ?, ?)", param.Family, param.Title, "{}", person_id, person_id)
	if err != nil {
		return DBErrReturn("新增文章", err)
	}
	count, _ = result.RowsAffected()
	if count != 1 {
		return SvrErrReturn("新增文章失败")
	}
	articleId, _ := result.LastInsertId()
	return SuccRet(articleId)
}

//编辑文章标题
func edit_family_article_title(tx *sql.Tx, person_id int64, jsonData string) *ReturnStruct {
	type Param struct {
		Article int64  `json:"article"` //文章id，如果是新增，则取0
		Family  int64  `json:"family"`  //家族id
		Title   string `json:"title"`   //新标题
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//校验article
	var count int64
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and family = ?", param.Article, param.Family).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return ParamErrReturn("校验数据异常")
	}

	//校验编辑人
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and create_person = ?", param.Article, person_id).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return SvrErrReturn("只有创建者可以编辑家族文章！")
	}

	//更新
	_, err = tx.Exec("update tb_family_article set title = ?, edit_person = ?, edit_timestamp = CURRENT_TIMESTAMP() where id = ?", param.Title, person_id, param.Article)
	if err != nil {
		return DBErrReturn("更新失败", err)
	}
	return SuccRet(nil)
}

//获取文章列表，简略信息，带分页
func get_family_article_list(tx *sql.Tx, person_id int64, jsonData string) *ReturnStruct {
	type Param struct {
		Family   int64 `json:"family"`   //家族id
		Page     int   `json:"page"`     //当前页，从1开始算
		PageSize int   `json:"pagesize"` //每页大小
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}
	if param.Page <= 0 || param.PageSize <= 0 {
		return ParamErrReturn("")
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//查找数据
	rows, err := tx.Query("select a.id, title, IFNULL(content_delta, '{}') as content_delta, IFNULL(b.name, '') as edit_person, edit_timestamp as edit_time from tb_family_article a left join tb_person b on a.edit_person = b.id  where a.family = ? order by a.id desc limit ? offset ?", param.Family, param.PageSize, param.PageSize*(param.Page-1))
	if err != nil {
		return DBErrReturn("查询出错", err)
	}
	lst, _ := SelectResultFromRows(rows)

	//返回结果
	result := make([]map[string]interface{}, 0)
	for i := 0; i < len(lst); i++ {
		content_delta, ok := lst[i]["content_delta"].(string)
		if ok {
			content_text, _ := DeltaTipText(content_delta, 255)
			lst[i]["content_text"] = content_text
			delete(lst[i], "content_delta")
		}
		result = append(result, lst[i])
	}
	return SuccRet(result)
}

//获取列表中的单个文章的数据，用于编辑文章后刷新，注意返回的格式和接口get_article_list返回的列表单项内容保持一致。
func get_single_family_article_in_list(tx *sql.Tx, person_id int64, jsonData string) *ReturnStruct {
	type Param struct {
		Family  int64 `json:"family"`  //家族id
		Article int64 `json:"article"` //文章ID
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//校验article
	var count int64
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and family = ?", param.Article, param.Family).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return ParamErrReturn("校验数据异常")
	}

	//查找数据
	rows, err := tx.Query("select a.id, title, IFNULL(content_delta, '{}') as content_delta, IFNULL(b.name, '') as edit_person, edit_timestamp as edit_time from tb_family_article a left join tb_person b on a.edit_person = b.id  where a.id = ? and a.family = ?", param.Article, param.Family)
	if err != nil {
		return DBErrReturn("查询出错", err)
	}
	lst, _ := SelectResultFromRows(rows)
	if len(lst) == 0 {
		return SvrErrReturn("查找失败")
	}

	//返回结果
	content_delta, ok := lst[0]["content_delta"].(string)
	if ok {
		content_text, _ := DeltaTipText(content_delta, 255)
		lst[0]["content_text"] = content_text
		delete(lst[0], "content_delta")
	}
	return SuccRet(lst[0])
}

//删除文章, 编辑人可以删
func del_family_article(tx *sql.Tx, person_id int64, jsonData string) (returnVal *ReturnStruct) {
	type Param struct {
		Family  int64 `json:"family"`  //修改人和被修改人公共的家族id
		Article int64 `json:"article"` //文章id
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//校验所属人
	var count int64
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and family = ?", param.Article, param.Family).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return ParamErrReturn("校验数据")
	}

	//校验删除人
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and create_person = ?", param.Article, person_id).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return SvrErrReturn("只有创建者可以删除家族文章！")
	}

	//先删评论
	_, err = tx.Exec("delete from tb_family_article_comment where article = ?", param.Article)
	if err != nil {
		return DBErrReturn("删除评论失败", err)
	}

	//删除图片
	rows, err := tx.Query("select id, filename from tb_family_article_pic where article = ?", param.Article)
	if err != nil {
		return DBErrReturn("查询图片", err)
	}
	picsResult, _ := SelectResultFromRows(rows)
	//注意： 当整个接口返回成功了再删除图片，避免中途失败了但图片已经删了
	defer func() {
		if returnVal.is_success() {
			for i := 0; i < len(picsResult); i++ {
				image_name, _ := picsResult[i]["filename"].(string)
				os.Remove("./file/" + image_name)
			}
		}
	}()
	_, err = tx.Exec("delete from tb_family_article_pic where article = ?", param.Article)
	if err != nil {
		return DBErrReturn("删除数据库图片", err)
	}

	//删除文章
	_, err = tx.Exec("delete from tb_family_article where id = ?", param.Article)
	if err != nil {
		return DBErrReturn("删除文章", err)
	}

	return SuccRet(nil)
}

//获取文章的评论列表
func api_get_family_article_comments(tx *sql.Tx, articleId int64) ([]map[string]interface{}, error) {
	rows, err := tx.Query("select a.*, b.name as person_name from tb_family_article_comment a left join tb_person b on a.edit_person = b.id where a.article = ? order by a.id", articleId)
	if err != nil {
		return nil, err
	}
	result, _ := SelectResultFromRows(rows)
	return result, nil
}

//增加文章评论
func add_family_article_comment(tx *sql.Tx, person_id int64, jsonData string) *ReturnStruct {
	type Param struct {
		Family  int64  `json:"family"`  //修改人和被修改人公共的家族id
		Article int64  `json:"article"` //文章id
		Comment string `json:"comment"` //评论内容
	}
	var param Param
	err := json.Unmarshal([]byte(jsonData), &param)
	if err != nil {
		return FailRet(CodeParamError, err)
	}

	if len(param.Comment) == 0 {
		return ParamErrReturn("评论为空")
	}
	if ChnLen(param.Comment) > 1024 {
		return ParamErrReturn("评论过长")
	}

	//校验当前人
	isContains, err := api_family_contain_person(tx, param.Family, []int64{person_id})
	if err != nil {
		return DBErrReturn("校验当前人异常", err)
	}
	if !isContains {
		return ParamErrReturn("校验当前人失败")
	}

	//校验所属人
	var count int64
	err = tx.QueryRow("select count(*) from tb_family_article where id = ? and family = ?", param.Article, param.Family).Scan(&count)
	if err != nil {
		return DBErrReturn("校验数据", err)
	}
	if count == 0 {
		return ParamErrReturn("校验数据")
	}

	//新增
	_, err = tx.Exec("insert into tb_family_article_comment(article, content, edit_person) values (?, ?, ?)", param.Article, param.Comment, person_id)
	if err != nil {
		return DBErrReturn("新增评论", err)
	}

	//返回评论列表
	comments, err := api_get_family_article_comments(tx, param.Article)
	if err != nil {
		return DBErrReturn("查找文章评论", err)
	}
	return SuccRet(comments)
}
